package com.fkdx.webman.filter;

import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.fkdx.common.constant.SysConstant;
import com.fkdx.common.dto.ResponseDTO;
import com.fkdx.common.dto.sys.CurrentUserDTO;
import com.fkdx.common.enums.sys.GroupException;
import com.fkdx.common.token.SecretKeyUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.PatternMatchUtils;
import org.springframework.util.StringUtils;

import javax.naming.NoPermissionException;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * 管理端token过滤
 *
 * @author Chopper
 */
@Log4j2
public class AuthenticationFilter extends BasicAuthenticationFilter {


    public AuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @SneakyThrows
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {

        //从header中获取jwt
        String jwt = request.getHeader(SysConstant.ACCESSTOKEN);
        //如果没有token 则return
        if (StringUtils.isEmpty(jwt)) {
            chain.doFilter(request, response);
            return;
        }

        //获取用户信息，存入context
        UsernamePasswordAuthenticationToken authentication = getAuthentication(jwt, response);

        if (authentication != null) {
            //customAuthentication(request, response, authentication);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } else {
            return;
        }
        chain.doFilter(request, response);
    }

    /**
     * 自定义权限过滤
     *
     * @param request        请求
     * @param response       响应
     * @param authentication 用户信息
     */
    private void customAuthentication(HttpServletRequest request, HttpServletResponse response, UsernamePasswordAuthenticationToken authentication) throws NoPermissionException {

    }

    /**
     * 校验权限
     *
     * @param permissions 权限集合
     * @param url         请求地址
     * @return 是否拥有权限
     */
    boolean match(List<String> permissions, String url) {
        if (permissions == null || permissions.isEmpty()) {
            return false;
        }
        return PatternMatchUtils.simpleMatch(permissions.toArray(new String[0]), url);
    }

    /**
     * 获取token信息
     *
     * @param jwt      token信息
     * @param response 响应
     * @return 获取鉴权对象
     */
    private UsernamePasswordAuthenticationToken getAuthentication(String jwt, HttpServletResponse response) {

        try {
            Claims claims
                    = Jwts.parser()
                    .setSigningKey(SecretKeyUtil.generalKeyByDecoders())
                    .parseClaimsJws(jwt).getBody();
            //获取存储在claims中的用户信息
            String json = claims.get(SysConstant.ACCESSTOKEN).toString();

            //log.info("用户信息：json==>{}", json);

            CurrentUserDTO authUser = new Gson().fromJson(json, CurrentUserDTO.class);

            //校验有效
            if ((claims.getExpiration().getTime() - System.currentTimeMillis()) > 0) {

                List<GrantedAuthority> auths = new ArrayList<>();
                //auths.add(new SimpleGrantedAuthority("ROLE_" + authUser.getUsername()));
                //构造返回信息
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(authUser.getUserName(), null, auths);
                authentication.setDetails(authUser);
                return authentication;
            }
            return null;
        } catch (ExpiredJwtException e) {
            log.debug("user analysis exception:", e);
            redirectToLogin(response);
        } catch (Exception e) {
            log.error("other exception:", e);
        }
        return null;
    }

    public void redirectToLogin(HttpServletResponse httpServletResponse)  {
        try {
            httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
            ResponseDTO<Object> responseContent = ResponseDTO.buildResponse(HttpStatus.UNAUTHORIZED.value(), "登录失效.", null);
            httpServletResponse.setCharacterEncoding("UTF-8");
            httpServletResponse.getWriter().write(JSON.toJSONString(responseContent));
            httpServletResponse.getWriter().close();
        } catch (Exception e) {
            throw new GroupException("login Expired.");
        }

    }
}

